package cn.cycleif.app.service;

import cn.cycleif.app.domain.dto.AnswerDTO;
import cn.cycleif.app.domain.vo.AnswerVO;
import cn.cycleif.app.mapper.AnswerMapper;
import cn.cycleif.app.mapper.QuestionMapper;
import cn.cycleif.entity.Answer;
import cn.cycleif.entity.Question;
import cn.cycleif.enums.CommonStatusEnum;
import cn.cycleif.enums.ObjectTypeEnum;
import cn.cycleif.enums.ResultCodeEnum;
import cn.cycleif.enums.VoteStatusEnum;
import cn.cycleif.util.PageUtil;
import cn.cycleif.util.R;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Date: 25/2/8-21:20
 * @Desc:
 */
@Service
@RequiredArgsConstructor
public class AnswerService extends ServiceImpl<AnswerMapper, Answer> {

  private final AnswerMapper    answerMapper;
  private final UserService     userService;
  private final QuestionMapper  questionMapper;
  private final QuestionService questionService;
  private final RedisService    redisService;

  public R<Object> getList(Integer questId, String order) {
    Page<Answer>               page    = new Page<>(PageUtil.getPageNo(), PageUtil.getPageSize());
    LambdaQueryWrapper<Answer> wrapper = new LambdaQueryWrapper<>();
    wrapper.eq(Answer::getStatus, CommonStatusEnum.ACTIVE);
    switch (order) {
      case "hot":
        wrapper.orderByDesc(Answer::getCommentCount);
        break;
      case "newest":
      default:
        wrapper.orderByDesc(Answer::getCreateAt);
        break;
    }
    wrapper.eq(Answer::getQuestionId, questId);
    Page<Answer>   page1  = answerMapper.selectPage(page, wrapper);
    Page<AnswerVO> voPage = new Page<>();
    voPage.setCurrent(page1.getCurrent());
    voPage.setSize(page1.getSize());
    voPage.setTotal(page1.getTotal());
    voPage.setPages(page1.getPages());

    List<Answer>   answers = page1.getRecords();
    List<AnswerVO> list    = answers.stream().map(this::appendExtraInfo).toList();
    voPage.setRecords(list);
    return R.success(voPage);
  }

  @NotNull
  private AnswerVO appendExtraInfo(Answer answer) {
    AnswerVO                answerVO = BeanUtil.copyProperties(answer, AnswerVO.class);
    HashMap<String, Object> userInfo = userService.getUserSimpleInfo(answer.getUserId(), null);
    answerVO.setUserInfo(userInfo);
    Integer voteCnt = redisService.getVoteCnt(ObjectTypeEnum.ANSWER, answer.getId());
    if (voteCnt != null) answerVO.setVoteCount(voteCnt + answer.getVoteCount());
    if (StpUtil.isLogin()) {
      int userId = StpUtil.getLoginIdAsInt();
      VoteStatusEnum status =
          redisService.getVoteStatus(ObjectTypeEnum.ANSWER, answer.getId(), userId);
      answerVO.setVoteStatus(status);
    }
    // TODO:添加评论信息
    return answerVO;
  }

  public R<Object> getUserAnswerList(Integer id) {
    LambdaQueryWrapper<Answer> wrapper = new LambdaQueryWrapper<>();
    wrapper.eq(Answer::getUserId, id);
    List<Answer> answers = answerMapper.selectList(wrapper);
    List<Map<String, Object>> list = answers.stream().map(v -> {
      Map<String, Object> map     = new HashMap<>();
      Integer             voteCnt = redisService.getVoteCnt(ObjectTypeEnum.ANSWER, v.getId());
      if (voteCnt != null) v.setVoteCount(voteCnt + v.getVoteCount());
      map.put("answerInfo", v);
      Question            question     = questionMapper.selectById(v.getQuestionId());
      Map<String, Object> questionInfo = new HashMap<>();
      questionInfo.put("id", question.getId());
      questionInfo.put("title", question.getTitle());
      List<Object> tagsInfo = questionService.getQuestionTagsInfo(question.getId());
      questionInfo.put("tags", tagsInfo);
      map.put("questionInfo", questionInfo);
      return map;
    }).toList();
    return R.success(list);
  }

  @Transactional
  public R<String> addAnswer(AnswerDTO dto) {
    Question question = questionMapper.selectById(dto.getQuestionId());
    if (question == null) return R.error(ResultCodeEnum.ERROR_NOT_EXIST);
    int    userId = StpUtil.getLoginIdAsInt();
    Answer answer = new Answer();
    answer.setContent(dto.getContent());
    answer.setQuestionId(dto.getQuestionId());
    answer.setUserId(userId);
    answer.setLastEditUserId(userId);
    answer.setStatus(CommonStatusEnum.ACTIVE);
    answerMapper.insert(answer);
    question.setAnswerCount(question.getAnswerCount() + 1);
    questionMapper.updateById(question);
    // TODO: 记录历史
    return R.success();
  }

  public R<String> updateAnswer(AnswerDTO dto) {
    Integer answerId = dto.getAnswerId();
    Answer  answer   = answerMapper.selectById(answerId);
    if (answer == null) return R.error(ResultCodeEnum.ERROR_NOT_EXIST);

    answer.setContent(dto.getContent());
    answerMapper.updateById(answer);
    // TODO: 记录历史

    return R.success();
  }

  @Transactional
  public R<String> deleteAnswer(Integer id) {
    long                       userId  = StpUtil.getLoginIdAsLong();
    LambdaQueryWrapper<Answer> wrapper = new LambdaQueryWrapper<>();
    wrapper.eq(Answer::getUserId, userId);
    wrapper.eq(Answer::getId, id);

    Answer answer = answerMapper.selectOne(wrapper);
    if (answer == null) return R.error(ResultCodeEnum.ERROR_NOT_EXIST);
    answer.setStatus(CommonStatusEnum.DELETE); // 标记删除
    answerMapper.updateById(answer);
    // 更新
    Question question = questionMapper.selectById(answer.getQuestionId());
    question.setAnswerCount(question.getAnswerCount() - 1);
    questionMapper.updateById(question);
    // TODO:记录
    return R.success();
  }
}
